﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
using Orchard.Entity;
using System.Data.Entity.Validation;
using System.Linq.Expressions;
using System.Data.Entity.Infrastructure;

namespace Orchard.Data
{
    /// <summary>
    /// 数据基类
    /// </summary>
    public abstract class RepositoryBase : DbContext
    {
        protected readonly DbContext _db;
        /// <summary>
        /// 为ioc提供入口点,如果有ioc配置，则优先
        /// </summary>
        /// <param name="db"></param>
        /// <param name="logger"></param>
        protected RepositoryBase(DbContext db)
        {
            _db = db;
        }
        public RepositoryBase()
            : this(new EEE114Entities())
        {

        }

        public void Update<TEntity>(Expression<Action<TEntity>> entity) where TEntity : class
        {
            TEntity newEntity = typeof(TEntity).GetConstructor(Type.EmptyTypes).Invoke(null) as TEntity;
            List<string> propertyNameList = new List<string>();
            MemberInitExpression param = entity.Body as MemberInitExpression;
            foreach (var item in param.Bindings)
            {
                string propertyName = item.Member.Name;
                object propertyValue;
                var memberAssignment = item as MemberAssignment;
                if (memberAssignment.Expression.NodeType == ExpressionType.Constant)
                {
                    var constantExpression = memberAssignment.Expression as ConstantExpression;
                    propertyValue = constantExpression.Value;
                }
                else
                {
                    LambdaExpression lambda = Expression.Lambda(memberAssignment.Expression, null);
                    propertyValue = lambda.Compile().DynamicInvoke();
                }
                typeof(TEntity).GetProperty(propertyName).SetValue(newEntity, propertyValue, null);
            }
            _db.Set<TEntity>().Attach(newEntity);
            var ObjectStateEntry = ((System.Data.Entity.Infrastructure.IObjectContextAdapter)this).ObjectContext.ObjectStateManager.GetObjectStateEntry(newEntity);
            propertyNameList.ForEach(x =>
            {
                ObjectStateEntry.SetModifiedProperty(x);
            });
        }

        protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items)
        {
            List<DbValidationError> errorList = new List<DbValidationError>();
            var res = base.ValidateEntity(entityEntry, items);
            foreach (var item in res.ValidationErrors)
            {
                if (entityEntry.Property(item.PropertyName).IsModified)
                    errorList.Add(item);
            }
            DbEntityValidationResult vResult = new DbEntityValidationResult(entityEntry, errorList);
            return vResult;
        }

    }
}